<?php

/*
 *  ===============================================
 *  cColor クラス Ver.071016_0647
 * ===============================================
 *
 *    ■使い方
 *
 *        cColorクラスからオブジェクト（インスタンス）を作って利用する。
 *
 *    例）
 *        include_once("cColor.inc");       (1)
 *        $oColor = new cColor("#b4af91");  (2)
 *
 *        1) cColorクラスの読み込み
 *        2) #b4af91の色のオブジェクトを作成
 *
 *    ■色を取り出す
 *    $oColor -> value;
 *    
 *    ■明るさを変える
 *    $oColor -> Brightness(-80);
 *    色相を保ちながら、プラス値は白に、マイナス値は黒に近づきます。
 *    値が、100で黒(#000000)、-100で(#FFFFFF)になります。0はオリジナル色（オブジェクト作成時に指定した色）のまま。
 *    上記サンプルは、オリジナル色から黒になるまでの80%の黒さ。
 *
 *    ■色を混ぜる
 *    $oColor -> Mix("#c03000",50);
 *    オリジナル色（オブジェクト作成時に指定した色）を、引数の色に近づけます。
 *    値はプラス値のみです。0でオリジナル色、100で引数の色になります。
 *    上記サンプルは、オリジナルと引数の色の中間色。（ 50% ）
 *
 *    ■色の強調
 *    $oColor -> strong(50);
 *    色相を保ちながらオリジナル色（オブジェクト作成時に指定した色）を元に白もしくは黒に近づけます。
 *    値はプラス値のみです。元の色を元に、白に近づけるか黒に近づけるか判断します。
 *    上記サンプルは、オリジナルと引数の色の中間色。（ 50% ）
 *
 *    ■Webセーフカラーに変換
 *    $oColor -> WebSafe("#b73909");
 *    与えられた色をWebセーフカラーに変換して返します。引数を指定しない場合は、オリジナル色を返します。
 *    上記サンプルは"#b73909"をWebセーフカラー("#cc3300")に変換。
 *
 *
 */

class cColor{

    var $r;
    var $g;
    var $b;
    var $rgb;
    var $value;

    //コンストラクタ
    function cColor($sColor=""){

        $sColor = Empty($sColor) ? $this->Random() : $sColor;

        $aTemp = $this->StrToRGB($sColor);
        $this -> r = $aTemp[0];
        $this -> g = $aTemp[1];
        $this -> b = $aTemp[2];
        $this -> rgb = $aTemp;
        $this -> value = $sColor;
    }

    //$this->value値の書き換え
    function set($s=""){
        if(Empty($s)) return FALSE;
        return ($this->cColor($s));
    }

    //#xxxxxxを10進RGBの配列に変換
    function StrToRGB($color){
        $color = str_replace('#','',$color);
        $color = strtolower($color);
        $len= strlen($color);
        if(!ereg('[^[:xdigit:]]+',$color) && ($len=="6" || $len=="3")){
            $d = $len /3;
            $r = substr($color,0*$d,$d);
            $g = substr($color,1*$d,$d);
            $b = substr($color,2*$d,$d);

            $a = ($len=="3") ? array($r.$r, $g.$g, $b.$b) : array($r,$g,$b); //#FFF 形式の場合

            return $this->HexDecRGB($a);

        }
        else{
            return FALSE;
        }
    }

    //ランダムな色を生成
    function Random(){
        $r = mt_rand(0,255);
        $g = mt_rand(0,255);
        $b = mt_rand(0,255);

        return $this -> FormatHex(array($r,$g,$b));
    }

    //10進RGBの配列を16進RGBに変換
    function HexDecRGB($a){

        return array( hexdec($a[0]), hexdec($a[1]), hexdec($a[2]) );

    }

    //10進RGBを#xxxxxx形式で返す
    function FormatHex($a=null){
        if($a==null){
            $a = $this->rgb;
        }
        $r = dechex($a[0]);
        $g = dechex($a[1]);
        $b = dechex($a[2]);

        //一桁を二桁に
        $r = (strlen($r) == 1) ? '0' . $r : $r;
        $g = (strlen($g) == 1) ? '0' . $g : $g;
        $b = (strlen($b) == 1) ? '0' . $b : $b;

        return "#" . $r . $g . $b;
    }

    //明度（輝度）値の算出
    function GetBrightnessDepth($s){
        $a = $this->StrToRGB($s);
        return round( MAX($a[0],$a[1],$a[2]) + MIN($a[0],$a[1],$a[2]),-1)/2;
    }

    //明度の変更
    function Brightness($i,$s=null){
        if($s<>null){
            $aRGB = $this->StrToRGB($s);
        }
        else{
            $aRGB = $this->rgb;
        }

        $iLevel = 100;

        if($i>0){
            $i = ($i>100) ? 100 : $i;
            $r_from = $aRGB[0]; $r_to = 255;
            $g_from = $aRGB[1]; $g_to = 255;
            $b_from = $aRGB[2]; $b_to = 255;
        }
        else{
            $i = ($i<-100) ? -100 : $i;
            $i = $i*-1;
            $r_from = $aRGB[0]; $r_to = 0;
            $g_from = $aRGB[1]; $g_to = 0;
            $b_from = $aRGB[2]; $b_to = 0;
        }

        $r = round((($r_from * ($iLevel - $i)) + ($r_to * $i)) / $iLevel);
        $g = round((($g_from * ($iLevel - $i)) + ($g_to * $i)) / $iLevel);
        $b = round((($b_from * ($iLevel - $i)) + ($b_to * $i)) / $iLevel);

        $r = ($r>255) ? 255 : ($r<0) ? 0 : $r;
        $g = ($g>255) ? 255 : ($g<0) ? 0 : $g;
        $b = ($b>255) ? 255 : ($b<0) ? 0 : $b;

        return $this -> FormatHex(array($r,$g,$b));
    }

    //Webセーフカラーへの変換
    function WebSafe($s=null){

        if($s==null){
            $aRGB = $this -> rgb;
        }
        else{
            $aRGB = $this -> StrToRGB($s); //10進のRGB配列へ
        }
        $r = $this -> GetNearestWebSafe($aRGB[0]);
        $g = $this -> GetNearestWebSafe($aRGB[1]);
        $b = $this -> GetNearestWebSafe($aRGB[2]);

        return $this -> FormatHex(array($r,$g,$b));
        //return "({$r})({$g})({$b})";
    }

    //近似値を返す
    function GetNearestWebSafe($i){
        // 0/51/102/153/204/255
        $iHalf = $this -> Compare($i,102,153);
        if($iHalf==102){
            $iHalf = $this -> Compare($i,51,102);
            if($iHalf==51){
                $iHalf = $this -> Compare($i,0,51);
                return ($iHalf==0) ? 0 : 51;
            }
            else{
                return 102;
            }
        }
        else{
            $aThreshold = array(153,204,255);
            $iHalf = $this -> Compare($i,204,255);
            if($iHalf==204){
                $iHalf = $this -> Compare($i,153,204);
                return ($iHalf==204) ? 204 : 153;
            }
            else{
                return 255;
            }
        }
    }

    function Compare($target,$a,$b){
        $a2 = abs($target - $a);
        $b2 = abs($target - $b);
        return ( $a2 < $b2 ) ? $a : $b;
        //return "{$target}:{$a}:{$b}:{$a2}:{$b2}";
    }

    function Mix($sTo,$i){
        $iLevel = 100;
        $aRGB_From = $this->rgb;
        $aRGB_To   = $this->StrToRGB($sTo);

        $i = ($i>100) ? 100 : ($i<0) ? 0 : $i;

        $r_from = $aRGB_From[0]; $r_to = $aRGB_To[0];
        $g_from = $aRGB_From[1]; $g_to = $aRGB_To[1];
        $b_from = $aRGB_From[2]; $b_to = $aRGB_To[2];

        $r = round((($r_from * ($iLevel - $i)) + ($r_to * $i)) / $iLevel);
        $g = round((($g_from * ($iLevel - $i)) + ($g_to * $i)) / $iLevel);
        $b = round((($b_from * ($iLevel - $i)) + ($b_to * $i)) / $iLevel);

        $r = ($r>255) ? 255 : ($r<0) ? 0 : $r;
        $g = ($g>255) ? 255 : ($g<0) ? 0 : $g;
        $b = ($b>255) ? 255 : ($b<0) ? 0 : $b;

        return $this -> FormatHex(array($r,$g,$b));
    }

    function strong($i,$s=null){
        if($s<>null){
            $aRGB = $this->StrToRGB($s);
        }
        else{
            $aRGB = $this->rgb;
        }

        $iLevel = 100;

        $i = ($i>100) ? 100 : ($i<0) ? 0 : $i;

        $r_from = $aRGB[0];
        $g_from = $aRGB[1];
        $b_from = $aRGB[2];

        $iSum = array_sum($aRGB);

        $r_to = ($iSum<384) ? 255 : 0;
        $g_to = ($iSum<384) ? 255 : 0;
        $b_to = ($iSum<384) ? 255 : 0;

        $r = round((($r_from * ($iLevel - $i)) + ($r_to * $i)) / $iLevel);
        $g = round((($g_from * ($iLevel - $i)) + ($g_to * $i)) / $iLevel);
        $b = round((($b_from * ($iLevel - $i)) + ($b_to * $i)) / $iLevel);

        $r = ($r>255) ? 255 : ($r<0) ? 0 : $r;
        $g = ($g>255) ? 255 : ($g<0) ? 0 : $g;
        $b = ($b>255) ? 255 : ($b<0) ? 0 : $b;

        return $this -> FormatHex(array($r,$g,$b));
    }

}
?>